﻿using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Way.Lib;
using static System.Formats.Asn1.AsnWriter;

namespace CheckIn.UserInfoHost.Infrastructures
{
    public class WechatService
    {
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly ILogger<WechatService> _logger;
        private readonly IMemoryCache _memoryCache;
        string _AccessToken;
        public string AccessToken => _AccessToken;
        public WechatService(IHttpClientFactory httpClientFactory, ILogger<WechatService> logger , IMemoryCache memoryCache)
        {
            _httpClientFactory = httpClientFactory;
            _logger = logger;
            _memoryCache = memoryCache;
        }

        public async Task GetToken()
        {
            var url = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={AppConfigs.WechatConfig.Current.AppId}&secret={AppConfigs.WechatConfig.Current.Secret}";
            var client = _httpClientFactory.CreateClient();
            var ret = await client.GetAsync(url);
            var txt = await ret.Content.ReadAsStringAsync();
            if (!ret.IsSuccessStatusCode)
            {
                throw new WebException(txt);
            }


            _logger.LogInformation(txt);

            var obj = txt.FromJson<GetTokenResponse>();
            _AccessToken = obj.access_token;

        }

        /// <summary>
        /// 检查文字内容是否合规
        /// </summary>
        /// <param name="content"></param>
        /// <param name="openId"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        /// <exception cref="WebException"></exception>
        /// <exception cref="ServiceException"></exception>
        public async Task TextCheck(string content, string openId)
        {
            //POST https://api.weixin.qq.com/wxa/msg_sec_check?access_token=ACCESS_TOKEN
            for (int i = 0; i < 10 && _AccessToken == null; i++)
            {
                await Task.Delay(1000);
            }
            if (_AccessToken == null)
                throw new InvalidOperationException("AccessToken is null");

            var client = _httpClientFactory.CreateClient();
            var url = $"https://api.weixin.qq.com/wxa/msg_sec_check?access_token={HttpUtility.UrlEncode(_AccessToken)}";

            var body = new
            {
                openid = openId,
                scene = 2,
                version = 2,
                content = content
            };

            var jsonContent = new StringContent(body.ToJsonString(), Encoding.UTF8, "application/json");


            var ret = await client.PostAsync(url, jsonContent);
            var txt = await ret.Content.ReadAsStringAsync();
            _logger.LogDebug($"TextCheck 响应:{txt}");

            if (!ret.IsSuccessStatusCode)
            {

                throw new WebException($"{ret.ReasonPhrase} {txt}");
            }

            var obj = txt.FromJson<TextCheckObject>();
            if (obj.result.suggest != "pass")
            {
                throw new ServiceException($"[{obj.result.suggest}]: 内容包含不合规的文字");
            }
        }

        public async Task ImageCheck(string imgUrl, string openId)
        {

            for (int i = 0; i < 10 && _AccessToken == null; i++)
            {
                await Task.Delay(1000);
            }
            if (_AccessToken == null)
                throw new InvalidOperationException("AccessToken is null");

            var client = _httpClientFactory.CreateClient();
            var url = $"https://api.weixin.qq.com/wxa/media_check_async?access_token={HttpUtility.UrlEncode(_AccessToken)}";

            var body = new
            {
                openid = openId,
                scene = 2,
                version = 2,
                media_type = 2,
                media_url = imgUrl
            };

            var jsonContent = new StringContent(body.ToJsonString(), Encoding.UTF8, "application/json");


            var ret = await client.PostAsync(url, jsonContent);
            var txt = await ret.Content.ReadAsStringAsync();
            _logger.LogDebug($"ImageCheck 响应:{txt}");

            if (!ret.IsSuccessStatusCode)
            {

                throw new WebException($"{ret.ReasonPhrase} {txt}");
            }

            var obj = txt.FromJson<ImageCheckResponse>();
            if (obj.errcode != 0)
            {
                throw new ServiceException(obj.errmsg);
            }

            TextChecResult result = null;
            for (int i = 0; i< 30; i ++ )
            {
                if (_memoryCache.TryGetValue(obj.trace_id, out result))
                {
                    _memoryCache.Remove(obj.trace_id);
                    break;
                }
                await Task.Delay(1000);
            }

            if(result != null && result.suggest != "pass")
            {
                throw new ServiceException($"[{result.suggest}]: 图片包含不合规的内容");
            }
        }

        public void NotifyImageCheckResult(string trace_id, TextChecResult result)
        {
            _logger.LogDebug($"收到检测结果：{trace_id} {result.suggest} {result.label}");
            _memoryCache.Set(trace_id, result, new MemoryCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1)
            });
        }

        public async Task<LoginResponse> Login(string js_code)
        {
            var url = $"https://api.weixin.qq.com/sns/jscode2session?appid={AppConfigs.WechatConfig.Current.AppId}&secret={AppConfigs.WechatConfig.Current.Secret}&js_code={js_code}&grant_type=authorization_code";
            var client = _httpClientFactory.CreateClient();
            var ret = await client.GetAsync(url);
            var txt = await ret.Content.ReadAsStringAsync();
            if (!ret.IsSuccessStatusCode)
            {
                throw new WebException($"{ret.ReasonPhrase} {txt}");
            }

            var obj = txt.FromJson<LoginResponse>();
            if (obj.errcode != 0)
            {
                _logger.LogError(txt);
                throw new ServiceException("登录失败");
            }

            return obj;
        }

       

    }


    public class GetTokenResponse
    {
        public string access_token { get; set; }
        public int expires_in { get; set; }
    }
    public class WechatResponse
    {
        public int errcode { get; set; }
        public string errmsg { get; set; }
    }

    public class LoginResponse : WechatResponse
    {
        public string openid { get; set; }
        public string session_key { get; set; }
        public string unionid { get; set; }
    }

    public class TextCheckObject : WechatResponse
    {
       
        public TextCheckDetail[] detail { get; set; }
        public string trace_id { get; set; }
        public TextChecResult result { get; set; }
    }

    public class TextChecResult
    {
        public string suggest { get; set; }
        public int label { get; set; }
    }

    public class TextCheckDetail
    {
        public string strategy { get; set; }
        public int errcode { get; set; }
        public string suggest { get; set; }
        public int label { get; set; }
        public int prob { get; set; }
    }
    public class ImageCheckResponse : WechatResponse
    {
        public string trace_id { get; set; }
    }
}
